package social.hub.impl.jersey.util;

import java.util.Collections;
import java.util.Map;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;

import social.hub.api.ApiConfig;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.filter.ClientFilter;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.api.json.JSONConfiguration;
import com.sun.jersey.client.apache.ApacheHttpClient;
import com.sun.jersey.client.apache.config.ApacheHttpClientConfig;
import com.sun.jersey.client.apache.config.DefaultApacheHttpClientConfig;
import com.sun.jersey.oauth.client.OAuthClientFilter;
import com.sun.jersey.oauth.signature.OAuthParameters;
import com.sun.jersey.oauth.signature.OAuthSecrets;

public class ResourceFactory {

	public static class ContentTypeFilter extends ClientFilter {

		@Override
		public ClientResponse handle(ClientRequest request) throws ClientHandlerException {

			ClientResponse response = getNext().handle(request);

			MultivaluedMap<String, String> headers = response.getHeaders();

			String contentType = headers.get("content-type").get(0);

			if (contentType.equals("text/javascript; charset=UTF-8")) {
				headers.put("content-type", Collections.singletonList(MediaType.APPLICATION_JSON));
			} else if (contentType.equals("text/xml;charset=UTF-8")) {
				headers.put("content-type", Collections.singletonList(MediaType.APPLICATION_XML));
			}

			return response;

		}

	}

	private static Client	INSTANCE;

	public static WebResource createResource(String url) {
		return createClient().resource(url);
	}

	public static WebResource createResource(String url, ApiConfig config) {
		return createResource(url, config, null);
	}

	public static WebResource createResource(String url, ApiConfig config, String scope) {

		OAuthParameters oauthParameters = new OAuthParameters().
				consumerKey(config.getApiKey()).
				token(config.getAccessKey());

		OAuthSecrets oauthSecrets = new OAuthSecrets().
				consumerSecret(config.getApiSecret()).
				tokenSecret(config.getAccessSecret());

		if (scope != null) {
			oauthParameters.put("scope", scope);
		}

		return createResource(url, oauthParameters, oauthSecrets);

	}

	public static WebResource createResource(String url, OAuthParameters oauthParameters, OAuthSecrets oauthSecrets) {
		WebResource resource = createResource(url);
		resource.addFilter(new OAuthClientFilter(INSTANCE.getProviders(), oauthParameters, oauthSecrets));
		return resource;
	}

	private synchronized static Client createClient() {

		if (INSTANCE == null) {

			ApacheHttpClientConfig config = new DefaultApacheHttpClientConfig();

			Map<String, Object> props = config.getProperties();
			props.put(ClientConfig.PROPERTY_FOLLOW_REDIRECTS, true);
			props.put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, 0);
			props.put(ClientConfig.PROPERTY_READ_TIMEOUT, 0);
			props.put(ApacheHttpClientConfig.PROPERTY_HANDLE_COOKIES, true);

			Map<String, Boolean> features = config.getFeatures();
			features.put(ClientConfig.FEATURE_DISABLE_XML_SECURITY, true);
			features.put(ClientConfig.FEATURE_FORMATTED, true);
			features.put(ClientConfig.FEATURE_XMLROOTELEMENT_PROCESSING, false);
			features.put(JSONConfiguration.FEATURE_POJO_MAPPING, true);

			INSTANCE = ApacheHttpClient.create(config);

			// INSTANCE.addFilter(new GZIPContentEncodingFilter());
			INSTANCE.addFilter(new LoggingFilter());
			INSTANCE.addFilter(new ContentTypeFilter());

		}

		return INSTANCE;

	}

}
